/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
 *
 * The information contained herein is property of Nordic Semiconductor ASA.
 * Terms and conditions of usage are described in detail in NORDIC
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 *
 * Licensees are granted free, non-transferable use of the information. NO
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 * the file.
 */

 /** @cond To make doxygen skip this file */
 
/** @file
 *
 * @defgroup ble_sdk_srv_gls Glucose Service
 * @{
 * @ingroup ble_sdk_srv
 * @brief Glucose Service module.
 *
 * @details This module implements the Glucose Service.
 *
 * @note The application must propagate BLE stack events to the Glucose Service module by calling
 *       ble_cgms_on_ble_evt() from the @ref softdevice_handler callback.
 */

#ifndef BLE_GLS_H__
#define BLE_GLS_H__

#include <stdint.h>
#include <stdbool.h>
#include "ble.h"
#include "ble_srv_common.h"

/**@brief Glucose feature */
#define BLE_GLS_FEATURE_LOW_BATT                       0x0001  /**< Low Battery Detection During Measurement Supported */
#define BLE_GLS_FEATURE_MALFUNC                        0x0002  /**< Sensor Malfunction Detection Supported */
#define BLE_GLS_FEATURE_SAMPLE_SIZE                    0x0004  /**< Sensor Sample Size Supported */
#define BLE_GLS_FEATURE_INSERT_ERR                     0x0008  /**< Sensor Strip Insertion Error Detection Supported */
#define BLE_GLS_FEATURE_TYPE_ERR                       0x0010  /**< Sensor Strip Type Error Detection Supported */
#define BLE_GLS_FEATURE_RES_HIGH_LOW                   0x0020  /**< Sensor Result High-Low Detection Supported */
#define BLE_GLS_FEATURE_TEMP_HIGH_LOW                  0x0040  /**< Sensor Temperature High-Low Detection Supported */
#define BLE_GLS_FEATURE_READ_INT                       0x0080  /**< Sensor Read Interrupt Detection Supported */
#define BLE_GLS_FEATURE_GENERAL_FAULT                  0x0010  /**< General Device Fault Supported */
#define BLE_GLS_FEATURE_TIME_FAULT                     0x0020  /**< Time Fault Supported */
#define BLE_GLS_FEATURE_MULTI_BOND                     0x0040  /**< Multiple Bond Supported */

/**@brief Glucose measurement flags */
#define BLE_GLS_MEAS_FLAG_TIME_OFFSET                  0x01    /**< Time Offset Present */
#define BLE_GLS_MEAS_FLAG_CONC_TYPE_LOC                0x02    /**< Glucose Concentration, Type, and Sample Location Present */
#define BLE_GLS_MEAS_FLAG_UNITS_KG_L                   0x00    /**< Glucose Concentration Units kg/L */
#define BLE_GLS_MEAS_FLAG_UNITS_MOL_L                  0x04    /**< Glucose Concentration Units mol/L */
#define BLE_GLS_MEAS_FLAG_SENSOR_STATUS                0x08    /**< Sensor Status Annunciation Present */
#define BLE_GLS_MEAS_FLAG_CONTEXT_INFO                 0x10    /**< Context Information Follows */

/**@brief Glucose measurement type */
#define BLE_GLS_MEAS_TYPE_CAP_BLOOD                    1       /**< Capillary whole blood */
#define BLE_GLS_MEAS_TYPE_CAP_PLASMA                   2       /**< Capillary plasma */
#define BLE_GLS_MEAS_TYPE_VEN_BLOOD                    3       /**< Venous whole blood */
#define BLE_GLS_MEAS_TYPE_VEN_PLASMA                   4       /**< Venous plasma */
#define BLE_GLS_MEAS_TYPE_ART_BLOOD                    5       /**< Arterial whole blood */
#define BLE_GLS_MEAS_TYPE_ART_PLASMA                   6       /**< Arterial plasma */
#define BLE_GLS_MEAS_TYPE_UNDET_BLOOD                  7       /**< Undetermined whole blood */
#define BLE_GLS_MEAS_TYPE_UNDET_PLASMA                 8       /**< Undetermined plasma */
#define BLE_GLS_MEAS_TYPE_FLUID                        9       /**< Interstitial fluid (ISF) */
#define BLE_GLS_MEAS_TYPE_CONTROL                      10      /**< Control solution */

/**@brief Glucose measurement location */
#define BLE_GLS_MEAS_LOC_FINGER                        1       /**< Finger */
#define BLE_GLS_MEAS_LOC_AST                           2       /**< Alternate Site Test (AST) */
#define BLE_GLS_MEAS_LOC_EAR                           3       /**< Earlobe */
#define BLE_GLS_MEAS_LOC_CONTROL                       4       /**< Control solution */
#define BLE_GLS_MEAS_LOC_NOT_AVAIL                     15      /**< Sample Location value not available */

/**@brief Glucose sensor status annunciation */
#define BLE_GLS_MEAS_STATUS_BATT_LOW                   0x0001  /**< Device battery low at time of measurement */
#define BLE_GLS_MEAS_STATUS_SENSOR_FAULT               0x0002  /**< Sensor malfunction or faulting at time of measurement */
#define BLE_GLS_MEAS_STATUS_SAMPLE_SIZE                0x0004  /**< Sample size for blood or control solution insufficient at time of measurement */
#define BLE_GLS_MEAS_STATUS_STRIP_INSERT               0x0008  /**< Strip insertion error */
#define BLE_GLS_MEAS_STATUS_STRIP_TYPE                 0x0010  /**< Strip type incorrect for device */
#define BLE_GLS_MEAS_STATUS_RESULT_HIGH                0x0020  /**< Sensor result higher than the device can process */
#define BLE_GLS_MEAS_STATUS_RESULT_LOW                 0x0040  /**< Sensor result lower than the device can process */
#define BLE_GLS_MEAS_STATUS_TEMP_HIGH                  0x0080  /**< Sensor temperature too high for valid test/result at time of measurement */
#define BLE_GLS_MEAS_STATUS_TEMP_LOW                   0x0100  /**< Sensor temperature too low for valid test/result at time of measurement */
#define BLE_GLS_MEAS_STATUS_STRIP_PULL                 0x0200  /**< Sensor read interrupted because strip was pulled too soon at time of measurement */
#define BLE_GLS_MEAS_STATUS_GENERAL_FAULT              0x0400  /**< General device fault has occurred in the sensor */
#define BLE_GLS_MEAS_STATUS_TIME_FAULT                 0x0800  /**< Time fault has occurred in the sensor and time may be inaccurate */

/**@brief Glucose measurement context flags */
#define BLE_GLS_CONTEXT_FLAG_CARB                      0x01    /**< Carbohydrate id and carbohydrate present */
#define BLE_GLS_CONTEXT_FLAG_MEAL                      0x02    /**< Meal present */
#define BLE_GLS_CONTEXT_FLAG_TESTER                    0x04    /**< Tester-health present */
#define BLE_GLS_CONTEXT_FLAG_EXERCISE                  0x08    /**< Exercise duration and exercise intensity present */
#define BLE_GLS_CONTEXT_FLAG_MED                       0x10    /**< Medication ID and medication present */
#define BLE_GLS_CONTEXT_FLAG_MED_KG                    0x00    /**< Medication value units, kilograms */
#define BLE_GLS_CONTEXT_FLAG_MED_L                     0x20    /**< Medication value units, liters */
#define BLE_GLS_CONTEXT_FLAG_HBA1C                     0x40    /**< Hba1c present */
#define BLE_GLS_CONTEXT_FLAG_EXT                       0x80    /**< Extended flags present */

/**@brief Glucose measurement context carbohydrate ID */
#define BLE_GLS_CONTEXT_CARB_BREAKFAST                 1       /**< Breakfast */
#define BLE_GLS_CONTEXT_CARB_LUNCH                     2       /**< Lunch */
#define BLE_GLS_CONTEXT_CARB_DINNER                    3       /**< Dinner */
#define BLE_GLS_CONTEXT_CARB_SNACK                     4       /**< Snack */
#define BLE_GLS_CONTEXT_CARB_DRINK                     5       /**< Drink */
#define BLE_GLS_CONTEXT_CARB_SUPPER                    6       /**< Supper */
#define BLE_GLS_CONTEXT_CARB_BRUNCH                    7       /**< Brunch */

/**@brief Glucose measurement context meal */
#define BLE_GLS_CONTEXT_MEAL_PREPRANDIAL               1       /**< Preprandial (before meal) */
#define BLE_GLS_CONTEXT_MEAL_POSTPRANDIAL              2       /**< Postprandial (after meal) */
#define BLE_GLS_CONTEXT_MEAL_FASTING                   3       /**< Fasting */
#define BLE_GLS_CONTEXT_MEAL_CASUAL                    4       /**< Casual (snacks, drinks, etc.) */
#define BLE_GLS_CONTEXT_MEAL_BEDTIME                   5       /**< Bedtime */

/**@brief Glucose measurement context tester */
#define BLE_GLS_CONTEXT_TESTER_SELF                    1       /**< Self */
#define BLE_GLS_CONTEXT_TESTER_PRO                     2       /**< Health care professional */
#define BLE_GLS_CONTEXT_TESTER_LAB                     3       /**< Lab test */
#define BLE_GLS_CONTEXT_TESTER_NOT_AVAIL               15      /**< Tester value not available */

/**@brief Glucose measurement context health */
#define BLE_GLS_CONTEXT_HEALTH_MINOR                   1       /**< Minor health issues */
#define BLE_GLS_CONTEXT_HEALTH_MAJOR                   2       /**< Major health issues */
#define BLE_GLS_CONTEXT_HEALTH_MENSES                  3       /**< During menses */
#define BLE_GLS_CONTEXT_HEALTH_STRESS                  4       /**< Under stress */
#define BLE_GLS_CONTEXT_HEALTH_NONE                    5       /**< No health issues */
#define BLE_GLS_CONTEXT_HEALTH_NOT_AVAIL               15      /**< Health value not available */

/**@brief Glucose measurement context medication ID */
#define BLE_GLS_CONTEXT_MED_RAPID                      1       /**< Rapid acting insulin */
#define BLE_GLS_CONTEXT_MED_SHORT                      2       /**< Short acting insulin */
#define BLE_GLS_CONTEXT_MED_INTERMED                   3       /**< Intermediate acting insulin */
#define BLE_GLS_CONTEXT_MED_LONG                       4       /**< Long acting insulin */
#define BLE_GLS_CONTEXT_MED_PREMIX                     5       /**< Pre-mixed insulin */

#define OPCODE_LENGTH  1                                                    /**< Length of opcode inside Glucose Measurement packet. */
#define HANDLE_LENGTH  2                                                    /**< Length of handle inside Glucose Measurement packet. */
#define MAX_GLM_LEN    (BLE_L2CAP_MTU_DEF - OPCODE_LENGTH - HANDLE_LENGTH)  /**< Maximum size of a transmitted Glucose Measurement. */

#define MAX_SIZE_CGM_MEAS 6
#define NB_MAX_RECORD_PER_NOTIFCATIONS (MAX_GLM_LEN/MAX_SIZE_CGM_MEAS)

#define MAX_AUTH_STR_LEN (MAX_GLM_LEN-3)
#define MIN_AUTHO_STRING_LEN 4

/**@brief SFLOAT format (IEEE-11073 16-bit FLOAT, meaning 4 bits for exponent (base 10) and 12 bits mantissa) */
typedef struct
{
  int8_t exponent;                                             /**< Base 10 exponent, should be using only 4 bits */
  int16_t mantissa;                                            /**< Mantissa, should be using only 12 bits */
} sfloat_t;

/**@brief Glucose Service event type. */
typedef enum
{
    BLE_GLS_EVT_NOTIFICATION_ENABLED,                          /**< Glucose value notification enabled event. */
    BLE_GLS_EVT_NOTIFICATION_DISABLED,                         /**< Glucose value notification disabled event. */
    BLE_GLS_EVT_START_SESSION,                                 /**< Glucose value notification start session event. */
    BLE_GLS_EVT_STOP_SESSION,                                  /**< Glucose value notification stop session event. */
    BLE_GLS_EVT_WRITE_COMM_INTERVAL                            /**< Glucose value write communication interval. */
} ble_cgms_evt_type_t;

/**@brief Glucose Service event. */
typedef struct
{
    ble_cgms_evt_type_t evt_type;                               /**< Type of event. */
} ble_cgms_evt_t;

// Forward declaration of the ble_cgms_t type. 
typedef struct ble_cgms_s ble_cgms_t;

/**@brief Glucose Service event handler type. */
typedef void (*ble_cgms_evt_handler_t) (ble_cgms_t * p_cgms, ble_cgms_evt_t * p_evt);


/**@brief Glucose Measurement structure. This contains glucose measurement value. */
typedef struct
{
    uint16_t glucose_concentration;                             /**< Glucose concentration */
    uint16_t time_offset;                                       /**< Time offset */
    uint16_t sensor_status_annunciation;                        /**< Sensor status annunciation */
} ble_cgms_meas_t;

/**@brief Glucose measurement record */
typedef struct
{
  ble_cgms_meas_t          meas;                                /**< Glucose measurement */
} ble_cgms_rec_t;

/**@brief Glucose feature structure. This contains the features support by the Glucose Service. */
typedef struct
{
    uint16_t     features;                                      /**< Field holding information on supported features in the continous glucose meter service */
    uint8_t      type;                                          /**< Type */
    uint8_t      sample_location;                               /**< Sample location */    
}ble_cgms_features_t;


/**@brief Glucose Service init structure. This contains all options and data needed for
 *        initialization of the service. */
typedef struct
{
    ble_cgms_evt_handler_t    evt_handler;                      /**< Event handler to be called for handling events in the Glucose Service. */
    ble_srv_error_handler_t   error_handler;                    /**< Function to be called in case of an error. */
    ble_cgms_features_t       feature_location_type;            /**< Features supported by the service. */
    uint8_t*                  authorization_string;             /**< Pointer to authorization string. */
    uint8_t                   authorization_str_len;            /**< Length of the authorization string. */
} ble_cgm_init_t;

/**@brief Specific Operation Control Point value structure. */
typedef struct
{
    uint8_t opcode;                                             /**< Op Code. */
    uint8_t operand_len;                                        /**< Length of the operand. */
    uint8_t *p_operand;                                         /**< Pointer to the operand. */
}ble_socp_value_t;

/**@brief Specific Operation Control Point response structure. */
typedef struct
{
    uint8_t opcode;                                             /**< Opcode describing the response. */
    uint8_t req_opcode;                                         /**< The original opcode for the request to which this response belongs. */
    uint8_t rsp_code;                                           /**< Response code. */
    uint8_t resp_val[MAX_GLM_LEN-2];                            /**< Array containing the response value. */
    uint8_t size_val;                                           /**< Length of the response value. */
}ble_socp_rsp_t;

/**@brief Glucose Service structure. This contains various status information for the service. */
typedef struct ble_cgms_s
{
    ble_cgms_evt_handler_t    evt_handler;                              /**< Event handler to be called for handling events in the Glucose Service. */
    ble_srv_error_handler_t   error_handler;                            /**< Function to be called in case of an error. */
    uint16_t                  service_handle;                           /**< Handle of Glucose Service (as provided by the BLE stack). */
    ble_gatts_char_handles_t  glm_handles;                              /**< Handles related to the Glucose Measurement characteristic. */
    ble_gatts_char_handles_t  glm_context_handles;                      /**< Handles related to the Glucose Measurement Context characteristic. */
    ble_gatts_char_handles_t  glf_handles;                              /**< Handles related to the Glucose Feature characteristic. */
    ble_gatts_char_handles_t  cgmsst_handles;                           /**< Handles related to the CGM Start Session Time characteristic. */
    ble_gatts_char_handles_t  racp_handles;                             /**< Handles related to the Record Access Control Point characteristic. */
    ble_gatts_char_handles_t  asp_handles;                              /**< Handles related to the Application Security Point characteristic. */
    ble_gatts_char_handles_t  socp_handles;                             /**< Handles related to the Sepcific Operations Control Point characteristic. */
    uint16_t                  conn_handle;                              /**< Handle of the current connection (as provided by the BLE stack, is BLE_CONN_HANDLE_INVALID if not in a connection). */
    ble_cgms_features_t       feature_location_type;                    
    uint8_t                   comm_interval;                            
    ble_socp_rsp_t            socp_response;                            
    ble_socp_rsp_t            ascp_response;                            
    uint8_t                   authorization_string[MAX_AUTH_STR_LEN];   
    uint8_t                   authorization_str_len;                    
    bool                      is_session_started;                       
    uint16_t                  patient_high_alert;                       
    uint16_t                  patient_low_alert;                        
    bool                      is_collector_authorized;                  
} ble_cgms_t;

/**@brief Function for sending glucose measurement/context.
 *
 * @param[in]   p_cgms   Service instance.
 * @param[in]   p_rec   Measurement to be sent.
 *
 * @return      NRF_SUCCESS on success, otherwise an error code.
 */
uint32_t glucose_meas_send(ble_cgms_t * p_cgms, ble_cgms_rec_t * p_rec, uint8_t *count);


/**@brief Function for initializing the Glucose Service.
 *
 * @details This call allows the application to initialize the Glucose Service.
 *
 * @param[out]  p_cgms       Glucose Service structure. This structure will have to be supplied by
 *                          the application. It will be initialized by this function, and will later
 *                          be used to identify this particular service instance.
 * @param[in]   p_gls_init  Information needed to initialize the service.
 *
 * @return      NRF_SUCCESS on successful initialization of service, otherwise an error code.
 */
uint32_t ble_cgms_init(ble_cgms_t * p_cgms, const ble_cgm_init_t * p_gls_init);

/**@brief Function for handling the Application's BLE Stack events.
 *
 * @details Handles all events from the BLE stack of interest to the Glucose Service.
 *
 * @param[in]   p_cgms      Glucose Service structure.
 * @param[in]   p_ble_evt  Event received from the BLE stack.
 */
void ble_cgms_on_ble_evt(ble_cgms_t * p_cgms, ble_evt_t * p_ble_evt);

/**@brief Function for reporting a new glucose measurement to the glucose service module.
 *
 * @details The application calls this function after having performed a new glucose measurement.
 *          The new measurement is recorded in the RACP database.
 *
 * @param[in]   p_cgms                    Glucose Service structure.
 * @param[in]   p_rec                    Pointer to glucose record (measurement plus context).
 *
 * @return      NRF_SUCCESS on success, otherwise an error code.
 */
uint32_t ble_cgms_glucose_new_meas(ble_cgms_t * p_cgms, ble_cgms_rec_t * p_rec);

#endif // BLE_GLS_H__

/** @} */

/** @endcond */
